/**
 * @PemTcpServerInitializer.java  COPYRIGHT xiaojian
 * 
 * Created on 2017年12月28日 下午3:51:23
 */
package xiaojian.toolkit.netty.initializer;

import javax.net.ssl.SSLEngine;

import org.springframework.core.io.Resource;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.SslProvider;

/**
 * PEM方式存储服务器端证书、单独的服务器端私钥。
 * 
 * @author <a href="mailto:cxj2000@gmail.com">xiaojian.cao</a>
 *
 */
public abstract class PemTcpServerInitializer extends SslBaseInitializer {

	private Resource keyCertResource = null;

	private Resource privateKeyResource = null;

	private ChannelHandler tcpRequestHandler;
	private ChannelHandler tcpResponseEncoder;

	@Override
	protected void addCodecHandler(ChannelPipeline pipeline) throws Exception {
		pipeline.addLast("tcpRequestDecoder", getTcpRequestDecoder()).addLast("tcpResponseEncoder", tcpResponseEncoder);
	}

	@Override
	protected void addBusinessHandler(ChannelPipeline pipeline) throws Exception {
		pipeline.addLast("handler", tcpRequestHandler);
	}

	public void setTcpRequestHandler(ChannelHandler tcpRequestHandler) {
		this.tcpRequestHandler = tcpRequestHandler;
	}

	public void setTcpResponseEncoder(ChannelHandler tcpResponseEncoder) {
		this.tcpResponseEncoder = tcpResponseEncoder;
	}

	public Resource getKeyCertResource() {
		return keyCertResource;
	}

	public void setKeyCertResource(Resource keyCertResource) {
		this.keyCertResource = keyCertResource;
	}

	public Resource getPrivateKeyResource() {
		return privateKeyResource;
	}

	public void setPrivateKeyResource(Resource privateKeyResource) {
		this.privateKeyResource = privateKeyResource;
	}

	@Override
	public void initChannel(Channel ch) throws Exception {
		if (isUseSsl()) {

			if (privateKeyResource == null || !privateKeyResource.exists()) {
				throw new Exception("Pls set privateKey file.");
			}

			if (keyCertResource == null || !keyCertResource.exists()) {
				throw new Exception("Pls set keycertificate file.");
			}

			SslContext sslContext = SslContextBuilder
					.forServer(keyCertResource.getInputStream(), privateKeyResource.getInputStream())
					.sslProvider(SslProvider.JDK).build();

			SSLEngine engine = sslContext.newEngine(ch.alloc());
			engine.setUseClientMode(false);
			ch.pipeline().addFirst("ssl", new SslHandler(engine));
		}

		super.initChannel(ch);
	}

	/**
	 * 注意tcpRequestDecoder必须确保是线程安全的 ,否则可能会出现解码时的未知异常
	 */
	public abstract ChannelHandler getTcpRequestDecoder();
}
